import copy
import re

from fastapi import APIRouter
from pydantic import BaseModel

from app.core.standard import UnifyResponse
from app.core.standard import default_return_value
from app.core.standard import update_to_much_rows_err_message_reg

from app.core.config import SQL_EXECUTE_USER

from .basic_utils import get_group_id_by_instance_info
from .basic_utils import get_master_info
from .basic_utils import goinception_handle
from .basic_utils import get_mysql_user_password
from .basic_utils import sql_analyze_filter
from .basic_utils import dml_large_execute

router = APIRouter()


class SQLExecuteItem(BaseModel):
    sql: str
    mysql_host: str
    mysql_port: int
    database_name: str = None
    operation: int  # 1: check 2: execute
    is_backup: int = 1  # 0: 不备份 1: 备份


@router.post(
    path="",
    name="SQL执行",
)
async def sql_handle(item: SQLExecuteItem):
    mysql_host = item.mysql_host
    mysql_port = item.mysql_port
    operation = item.operation
    sql_to_execute = item.sql
    database_name = item.database_name
    is_backup = item.is_backup

    return_code = copy.deepcopy(default_return_value)
    group_id = get_group_id_by_instance_info(mysql_host, mysql_port)
    master_info = get_master_info(group_id=group_id)

    if master_info is None:
        return_code.update({'message': "找不到对应的实例主库", 'error_code': 2})
        return UnifyResponse(data=None, extra_info=None,
                             **return_code)

    mysql_con_host = master_info.get('master_host')
    mysql_con_port = master_info.get('master_port')
    mysql_password = get_mysql_user_password(mysql_host=mysql_host, mysql_port=mysql_port, user_name=SQL_EXECUTE_USER)

    goinception_execute_return_info = goinception_handle(sql_to_execute=sql_to_execute, mysql_con_host=mysql_con_host,
                                                         mysql_con_port=mysql_con_port,
                                                         mysql_con_user=SQL_EXECUTE_USER, mysql_con_psw=mysql_password,
                                                         operation=1, database_name=database_name,
                                                         is_backup=is_backup)
    mysql_connect_dict = {'mysql_con_host': mysql_con_host,
                          'mysql_con_port': mysql_con_port,
                          'mysql_con_user': SQL_EXECUTE_USER,
                          'mysql_con_psw': mysql_password,
                          'database': database_name}

    if goinception_execute_return_info is None:
        return_code.update({'message': "sql执行出现错误", 'error_code': 2})
    for goinception_check_info in goinception_execute_return_info:
        if goinception_check_info.get('error_level') != 0:
            error_message = goinception_check_info.get('error_message')
            match_obj = re.fullmatch(update_to_much_rows_err_message_reg, error_message)
            if goinception_check_info.get('error_level') == 1 and match_obj is not None:
                dml_exec_result, result_msg = dml_large_execute(sql=sql_to_execute, mysql_info=mysql_connect_dict)
                if dml_exec_result != 1:
                    return_code.update({'message': "语句执行失败", 'error_code': 2})
                    return UnifyResponse(data=goinception_execute_return_info, extra_info=master_info,
                                         **return_code)
                return UnifyResponse(data=goinception_execute_return_info, extra_info=master_info,
                                     **return_code)
            return_code.update({'message': "sql执行出现错误", 'error_code': 2})
            return UnifyResponse(data=goinception_execute_return_info, extra_info=master_info,
                                 **return_code)

    check_result_list = sql_analyze_filter(sql_to_execute, operation=operation, database_name=database_name,
                                           mysql_connect_dict=mysql_connect_dict)
    # print(check_result_list)
    for check_result in check_result_list:
        if check_result.get('level') == 2:
            return_code.update({'message': "自定义检查发现不符合规范", 'error_code': 2})
            return UnifyResponse(data=goinception_execute_return_info, extra_info=check_result,
                                 **return_code)

    if operation == 2:
        goinception_execute_return_info = goinception_handle(sql_to_execute=sql_to_execute,
                                                             mysql_con_host=mysql_con_host,
                                                             mysql_con_port=mysql_con_port,
                                                             mysql_con_user=SQL_EXECUTE_USER,
                                                             mysql_con_psw=mysql_password,
                                                             operation=2, database_name=database_name,
                                                             is_backup=is_backup)

    for check_result in check_result_list:
        if check_result.get('level') == 1:
            return_code.update({'message': "自定义检查警告", 'error_code': 1})
            return UnifyResponse(data=goinception_execute_return_info, extra_info=check_result,
                                 **return_code)
    for check_result in check_result_list:
        if check_result.get('level') == 3:
            return_code.update({'message': "自定义检查建议:", 'error_code': 1})
            return UnifyResponse(data=goinception_execute_return_info, extra_info=check_result,
                                 **return_code)
    return UnifyResponse(data=goinception_execute_return_info, extra_info=None,
                         **return_code)
